package cmd

import (
	"context"
	"fmt"
	"github.com/spf13/cobra"
	"gogame/gameconfig"
	"gogame/lib"
	"gogame/logger"
	"gogame/server/rpcx"
	"gogame/server/rpcx/client"
	"gogame/server/rpcx/param"
	"net/http"
	"sync"
)

/*
	服务停止
*/

var StopCmd = &cobra.Command{
	Use:  "stop",
	Long: "stop 服务名...(不指定服务名默认停止所有)",
	Run:  Stop,
}

var api = rpcx.GetDefaultServiceName()

func init() {
	StopCmd.Flags().String("gatewayUrl", "", "gateway listen")
	StopCmd.Flags().String("workerUrl", "", "worker listen")
	RootCmd.AddCommand(StopCmd)

}

func Stop(cmd *cobra.Command, stopServiceNames []string) {
	_stopServiceNames := []string{"all"}
	if len(stopServiceNames) > 0 {
		_stopServiceNames = stopServiceNames
	}

	// 多个命令中包含all，只留all
	if len(_stopServiceNames) > 1 && lib.InSliceString("all", _stopServiceNames) {
		_stopServiceNames = []string{"all"}
	}

	for _, stopServiceName := range _stopServiceNames {
		switch stopServiceName {
		// 停止所有服务
		case "all":
			StopAll(cmd)
		// 停止游戏逻辑
		case "worker":
			StopWorker(cmd)
		// 停止网关
		case "gateway":
			StopGateway(cmd)
		// 停止定时器
		case "timer":
			StopTimer(cmd)
		// 停止数据入库
		case "modellog":
			StopModelLog(cmd)
		default:
			fmt.Printf("%s 服务不存在", stopServiceName)
		}

	}

}

func StopAll(cmd *cobra.Command) {
	// 先关掉网关
	StopGateway(cmd)

	StopTimer(cmd)
	StopModelLog(cmd)

	// 最后关worker
	StopWorker(cmd)
}

func StopWorker(cmd *cobra.Command) {
	_workerUrl, _ := cmd.Flags().GetString("workerUrl")
	if _workerUrl == "" {
		StopTimer(cmd)
		StopModelLog(cmd)
	}

	logger.Print("StopWorker start")
	_rpcxClient := client.NewRpcXClient("cmd_StopWorker", api, nil)
	_rpcxClient.SetMsgHandleNum(0)
	_rpcxClient.Dial(false)
	_rpcxClient.Fork(
		context.Background(),
		"StopWorker",
		_workerUrl,
		&param.AnyRes{},
	)
	_rpcxClient.Close()
	logger.Print("StopWorker end\n")
}

func StopGateway(cmd *cobra.Command) {
	_gatewayUrl, _ := cmd.Flags().GetString("gatewayUrl")

	logger.Print("StopGateway start")
	_wg := sync.WaitGroup{}
	for _, listen := range gameconfig.ServerConfig.Gateway {
		// 停止指定gateway
		if _gatewayUrl != "" && _gatewayUrl != listen {
			continue
		}

		_wg.Add(1)
		go func(listen string) {
			defer _wg.Done()
			_res, _err := http.Get(fmt.Sprintf("http://%s/stop_gateway", listen))
			if _err != nil {
				logger.Print("%s stop fail!! err->%v", listen, _err)
				return
			}
			if _res.Status == "200 OK" {
				logger.Print("%s stop success!!", listen)
			} else {
				logger.Print("%s stop fail!! Status->%v", listen, _res.Status)
			}
		}(listen)
	}

	_wg.Wait()
	logger.Print("StopGateway end\n")

}

/*

	timer和modelLog没有自己的端口
	通过worker转发到timer和modelLog实现服务停止
*/

func StopTimer(cmd *cobra.Command) {
	logger.Print("StopTimer start")
	sendRequest("cmd_StopTimer", "StopTimer")
	logger.Print("StopTimer end\n")
}

func StopModelLog(cmd *cobra.Command) {
	logger.Print("StopModelLog start")
	sendRequest("cmd_StopModelLog", "StopModelLog")
	logger.Print("StopModelLog end\n")
}

func sendRequest(listen, methodName string) {
	_rpcxClient := client.NewRpcXClient(listen, api, nil)
	_rpcxClient.SetMsgHandleNum(0)
	_rpcxClient.Dial(false)
	_rpcxClient.Fork(
		context.Background(),
		methodName,
		"",
		&param.AnyRes{},
	)
	_rpcxClient.Close()
}
